package com.zx.wx;

import com.zx.web.Login;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@SuppressWarnings("serial")
public class weixin extends HttpServlet {
	private static Logger logger = LogManager.getLogger(Login.class);

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String signature = req.getParameter("signature");
		String timestamp = req.getParameter("timestamp");
		String nonce = req.getParameter("nonce");
		String echostr = req.getParameter("echostr");
		String token = "weixin";
		logger.info("signature=" + signature + "&timestamp=" + timestamp + "&nonce=" + nonce + "&echostr=" + echostr);
		
		String[] a = new String[] { token, timestamp, nonce };
		Arrays.sort(a);
		String c = "";
		for (String b : a) {
			c += b;
		}
		String encode=encodeSHA1(c.toString());
		if (encode.equals(signature)) {
			PrintWriter out = resp.getWriter();
			out.print(echostr);
			out.close();
		} else {
			logger.info("服务器配置不匹配，校验失败");
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream()));
		String line = null;
		StringBuilder Msg = new StringBuilder();
		while ((line = br.readLine()) != null) {
			Msg.append(line);
		}
		logger.info("wxContent:"+line);
		Map<String,String> resultMap=xmlToMap(Msg.toString());
		String xml=PassiveReply(resultMap);
		
		logger.info("xml:"+xml);
		resp.setContentType("application/xml");
		resp.setCharacterEncoding("UTF-8");
		PrintWriter out=resp.getWriter();  
		out.write("success");
		out.flush();
		out.close();
	}
	
	//被动回复
	public String PassiveReply(Map<String,String> resultMap){
		String xml=null;
		switch (resultMap.get("MsgType")) {
		case "text": //文字小心
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[text]]></MsgType>"
					+ "<Content><![CDATA[你好]]></Content>"
					+ "</xml>";
			break;
		case "image": //图片消息
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[image]]></MsgType>"
					+ "<Image>"
					+ "<MediaId><![CDATA[media_id]]></MediaId>"
					+ "</Image>"
					+ "</xml>";
			break;
		case "voice": //语音消息
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[voice]]></MsgType>"
					+ "<Voice>"
					+ "<MediaId><![CDATA[media_id]]></MediaId>"
					+ "</Voice>"
					+ "</xml>";
			break;
		case "video": //视频消息
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[video]]></MsgType>"
					+ "<Video>"
					+ "<MediaId><![CDATA[media_id]]></MediaId>"
					+ "<Title><![CDATA[title]]></Title>"
					+ "<Description><![CDATA[description]]></Description>"
					+ "</Video> "
					+ "</xml>";
			break;
		case "shortvideo": //小视频消息 ,回复音乐消息
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[music]]></MsgType>"
					+ "<Music>"
					+ "<Title><![CDATA[TITLE]]></Title>"
					+ "<Description><![CDATA[DESCRIPTION]]></Description>"
					+ "<MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>"
					+ "<HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>"
					+ "<ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>"
					+ "</Music>"
					+ "</xml>";
			break;
		case "location": //地理位置  // 回复图文消息
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[news]]></MsgType>"
					+ "<ArticleCount>2</ArticleCount>"
					+ "<Articles>"
					+ "<item>"
					+ "<Title><![CDATA[title1]]></Title>"
					+ "<Description><![CDATA[description1]]></Description>"
					+ "<PicUrl><![CDATA[picurl]]></PicUrl>"
					+ "<Url><![CDATA[url]]></Url>"
					+ "</item>"
					+ "<item>"
					+ "<Title><![CDATA[title]]></Title>"
					+ "<Description><![CDATA[description]]></Description>"
					+ "<PicUrl><![CDATA[picurl]]></PicUrl>"
					+ "<Url><![CDATA[url]]></Url>"
					+ "</item>"
					+ "</Articles>"
					+ "</xml>";
			break;
		case "link": //链接消息
			xml="<xml>"
					+ "<ToUserName><![CDATA["+resultMap.get("FromUserName")+"]]></ToUserName>"
					+ "<FromUserName><![CDATA["+resultMap.get("ToUserName")+"]]></FromUserName>"
					+ "<CreateTime>"+System.currentTimeMillis()+"</CreateTime>"
					+ "<MsgType><![CDATA[text]]></MsgType>"
					+ "<Content><![CDATA[链接]]></Content>"
					+ "</xml>";
			break;
		case "event" :
			switch (resultMap.get("Event")) {
			case "subscribe": //关注、取消关注
				resultMap.get("ToUserName");//开发者微信号
				resultMap.get("FromUserName");//发送方帐号（一个OpenID）
				resultMap.get("CreateTime");//消息创建时间 （整型）
				resultMap.get("MsgType");//消息类型，event
				resultMap.get("Event");//事件类型，subscribe
				resultMap.get("EventKey");//事件KEY值，qrscene_为前缀，后面为二维码的参数值
				resultMap.get("Ticket");//二维码的ticket，可用来换取二维码图片
				break;
			case "SCAN": //用户已关注
				resultMap.get("ToUserName");//开发者微信号
				resultMap.get("FromUserName");//发送方帐号（一个OpenID）
				resultMap.get("CreateTime");//消息创建时间 （整型）
				resultMap.get("MsgType");//消息类型，event
				resultMap.get("Event");//事件类型，SCAN
				resultMap.get("EventKey");//事件KEY值，是一个32位无符号整数，即创建二维码时的二维码scene_id
				resultMap.get("Ticket");//二维码的ticket，可用来换取二维码图片		
				break;
			case "LOCATION"://上报地理位置
				resultMap.get("ToUserName");//开发者微信号
				resultMap.get("FromUserName");//发送方帐号（一个OpenID）
				resultMap.get("CreateTime");//消息创建时间 （整型）
				resultMap.get("MsgType");//消息类型，event
				resultMap.get("Event");//事件类型，LOCATION
				resultMap.get("Latitude");//地理位置纬度
				resultMap.get("Longitude");//地理位置经度
				resultMap.get("Precision");//地理位置精度
				break;
			case "CLICK"://自定义菜单resultMap.get("ToUserName");//开发者微信号
				resultMap.get("ToUserName");//开发者微信号
				resultMap.get("FromUserName");//发送方帐号（一个OpenID）
				resultMap.get("CreateTime");//消息创建时间 （整型）
				resultMap.get("MsgType");//消息类型，event
				resultMap.get("Event");//事件类型，CLICK
				resultMap.get("EventKey");//事件KEY值，与自定义菜单接口中KEY值对应
				break;
			case "VIEW"://点击菜单跳转链接时的事件推送
				resultMap.get("ToUserName");//开发者微信号
				resultMap.get("FromUserName");//发送方帐号（一个OpenID）
				resultMap.get("CreateTime");//消息创建时间 （整型）
				resultMap.get("MsgType");//消息类型，event
				resultMap.get("Event");//事件类型，VIEW
				resultMap.get("EventKey");//事件KEY值，设置的跳转URL
				break;
			default:
				xml="";
				break;
			}
			
			
			break;
		default:
			xml="";//内容不匹配，回复success，不显示“该公众号暂时无法提供服务，请稍后再试”
			break;
		}
		return xml;
	}
	
	public static String encodeSHA1(String str) {
		if (str == null) {
			return null;
		}
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
			messageDigest.update(str.getBytes());
			return getFormattedText(messageDigest.digest());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	
	}
	/**
	 * Takes the raw bytes from the digest and formats them correct.
	 *
	 * @param bytes
	 *            the raw bytes from the digest.
	 * @return the formatted bytes.
	 */
	private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
	private static String getFormattedText(byte[] bytes) {
		int len = bytes.length;
		StringBuilder buf = new StringBuilder(len * 2);
		// 把密文转换成十六进制的字符串形式
		for (int j = 0; j < len; j++) {
			buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
			buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
		}
		return buf.toString();
	}
	
	@SuppressWarnings("finally")
	public static Map<String,String> xmlToMap(String xml){
//		 String content = "<xml><URL><![CDATA[http://211.149.202.130/cms/wx]]></URL><ToUserName><![CDATA[okYfGv9twGuc-_i1aiJ4lgi5_REc]]></ToUserName><FromUserName><![CDATA[okYfGv9nc-kNIuJjNgb-VGHh1n3o]]></FromUserName><CreateTime>2016</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[sadfaasdfsfgsdgdgsfafsfafsfsafsf]]></Content><MsgId>111</MsgId></xml>";           
	        Document document=null;
	        Map<String,String> resultMap=new HashMap<>();
			try {
				document = DocumentHelper.parseText(xml);
				Element root = document.getRootElement();  
				for(Iterator<?> it=root.elementIterator();it.hasNext();){      
				        Element element = (Element) it.next();
				        resultMap.put(element.getName(), element.getText());
				 } 
			} catch (DocumentException e) {
				logger.error("xmlToMap:"+e.getMessage());
			}finally {
				return resultMap;
			} 
			
	}
}
